package com.xzj.spring.entity;

import com.xzj.spring.annotation.AliasFor;
import lombok.Data;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ProjectName: SpringDemo
 * @Package: com.xzj.spring.entity
 * @ClassName: DefaultAnnotationAttributeExtractor
 * @Author: xzj
 * @Description: 存放被AliasFor修饰的方法和值
 * @Date: 2022/7/15 11:25
 * @Version: 1.0
 */
@Data
public class DefaultAnnotationAttributeExtractor {

    private Class<? extends Annotation> parentAnnotation;

    private Map<String, Object> attributeMap = new ConcurrentHashMap<>(8);

    public DefaultAnnotationAttributeExtractor(Annotation an) {
        boolean b = false;
        Method[] methods = an.annotationType().getDeclaredMethods();
        for (Method method : methods) {
            //过滤掉注解中的隐藏方法
            if ("toString".equals(method.getName())) {
                continue;
            }
            if ("equals".equals(method.getName())) {
                continue;
            }
            if ("hashCode".equals(method.getName())) {
                continue;
            }
            if ("annotationType".equals(method.getName())) {
                continue;
            }
            //如果注解使用了别名
            AliasFor aliasFor = method.getAnnotation(AliasFor.class);
            //说明有别名
            if (aliasFor != null) {
                try {
                    //获得元注解（父注解）
                    parentAnnotation = aliasFor.annotation();
                    //获得父注解
                    if (parentAnnotation != null && !b) {
                        b = true; //表示处理了一次
                        //父类注解class
                        Class<? extends Annotation> clz = an.annotationType();
                        Annotation annotation = clz.getAnnotation(parentAnnotation);
                        //获取元注解中所有方法
                        Method[] parentClassMethods = annotation.getClass().getDeclaredMethods();
                        for (Method parentClassMethod : parentClassMethods) {
                            //过滤掉注解中的隐藏方法
                            if("toString".equals(parentClassMethod.getName())){
                                continue;
                            }
                            if("equals".equals(parentClassMethod.getName())){
                                continue;
                            }
                            if("hashCode".equals(parentClassMethod.getName())){
                                continue;
                            }
                            if("annotationType".equals(parentClassMethod.getName())){
                                continue;
                            }
                            method.setAccessible(true);
                            Object invoke = parentClassMethod.invoke(annotation, new Object[]{});
                            attributeMap.put(parentClassMethod.getName(),invoke);
                        }
                    }
                    method.setAccessible(true);
                    Object invoke = method.invoke(an, new Object[]{});
                    attributeMap.put(method.getName(), invoke);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
